/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.search.strategy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.groupme.model.Group;
import net.groupme.model.MODEL_CONSTANTS;
import net.groupme.model.ObjectFactory;
import net.groupme.model.Resource;
import net.groupme.model.Tag;
import net.groupme.search.strategy.model.WeightedResource;
import net.groupme.search.strategy.model.WeightedIdentifiableComparatorByWeight;

/**
 * created on Jul 3, 2007
 * 
 * This is a very simple {@link SearchStrategy} implementation. It only searches 
 * for resources and groups that are directly tagged with the given tags.
 * 
 * @author Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.7 $ $Date: 2007-07-11 18:57:19 $
 */
public class SearchOnlyForDierectlyTaggedResources implements SearchStrategy {
	
	/** Logger for this class and subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	/* (non-Javadoc)
	 * @see net.groupme.search.strategy.SearchStrategy#searchForGroups(java.util.Collection, boolean)
	 */
	public List<Group> searchForGroups(Collection<Tag> tags, boolean allTags) {
		List<WeightedResource> suitingResources = new ArrayList<WeightedResource>();
		//return an empty collection if no tags are specified
		if(tags.isEmpty()){
			return new ArrayList<Group>();
		}
		
		int count = 0;
		for(Tag tag: tags){
			//Case allTags == false (search for any = OR-connection) 
			//or the first step within the case allTags == false (search for all ) 
			if(!allTags || count == 0){
				WeightedResource actualResource = null;
				for(Resource resource: tag.getResources()){
					if(MODEL_CONSTANTS.RESOURCE_TYPE_GROUP.equals(resource.getType())){
						actualResource = new WeightedResource(resource, 1.0);
						if(suitingResources.contains(actualResource)){
							int pos = suitingResources.indexOf(actualResource);
							suitingResources.get(pos).weight += 1.0;
						}else{
							suitingResources.add(actualResource);
						}
					}
				}
			}
			//next steps within the case allTags == true (search for all) -> all resources that are 
			//not tagges with all other tags have to be removed 
			else{
				Collection<Resource> candidateResources = tag.getResources();
				List<WeightedResource> actualSuitingResources = new ArrayList<WeightedResource>();
				actualSuitingResources.addAll(suitingResources);
				for(WeightedResource resource: actualSuitingResources){
					//remove all resources that are not tagged with the first given tag:
					if(!candidateResources.contains(resource.getIdentifiable())){
						suitingResources.remove(resource);
					}
				}
				//to weight resources in this case is not necessary (da ja eh nur die resources geadded werden, die alle Tags aufweisen)
			}
			count++;
		}
		Collections.sort(suitingResources, new WeightedIdentifiableComparatorByWeight());
		
		//put groups of ordered map into a list:
		List<Group> resultList = new ArrayList<Group>();
		for(int i=0; i<suitingResources.size(); i++){
			resultList.add(ObjectFactory.getGroup(suitingResources.get(i).resource.getURI()));
		}
		return resultList;
	}

	/* (non-Javadoc)
	 * @see net.groupme.search.strategy.SearchStrategy#searchForResources(java.util.Collection, boolean, boolean)
	 */
	public List<Resource> searchForResources(Collection<Tag> tags, boolean allTags, boolean noGroups) {
		List<WeightedResource> suitingResources = new ArrayList<WeightedResource>();
		//return an empty collection if no tags are specified
		if(tags.isEmpty()){
			return new ArrayList<Resource>();
		}
		int count = 0;
		for(Tag tag: tags){
			//Case allTags == false (search for any = OR-connection) 
			//or the first step within the case allTags == false (search for all ) 
			if(!allTags || count == 0){
				WeightedResource actualResource = null;
				for(Resource resource: tag.getResources()){
					if(!noGroups || !MODEL_CONSTANTS.RESOURCE_TYPE_GROUP.equals(resource.getType())){
						actualResource = new WeightedResource(resource, 1.0);
						if(suitingResources.contains(actualResource)){
							int pos = suitingResources.indexOf(actualResource);
							suitingResources.get(pos).weight += 1.0;
						}else{
							suitingResources.add(actualResource);
						}
					}
				}
			}
			//next steps within the case allTags == true (search for all) -> all resources that are 
			//not tagges with all other tags have to be removed 
			else{
				Collection<Resource> candidateResources = tag.getResources();
				List<WeightedResource> actualSuitingResources = new ArrayList<WeightedResource>();
				actualSuitingResources.addAll(suitingResources);
				for(WeightedResource resource: actualSuitingResources){
					//remove all resources that are not tagged with the first given tag:
					if(!candidateResources.contains(resource.getIdentifiable())){
						suitingResources.remove(resource);
					}
				}
				//to weight resources in this case is not necessary (da ja eh nur die resources geadded werden, die alle Tags aufweisen)
			}
			count++;
		}
		Collections.sort(suitingResources, new WeightedIdentifiableComparatorByWeight());
		
		//put resources of ordered map into a list:
		List<Resource> resultList = new ArrayList<Resource>();
		for(int i=0; i<suitingResources.size(); i++){
			resultList.add(suitingResources.get(i).resource);
		}
		return resultList;
	}

}
